package com.baseframe.auth.granter;


import com.baseframe.auth.entity.BaseUserDetails;

import com.baseframe.auth.utils.WrapperUtil;
import com.baseframe.system.entity.BasePermission;
import com.baseframe.system.feign.BaseSystemFeign;
import com.baseframe.tool.container.Kv;
import com.baseframe.tool.result.R;
import com.baseframe.tool.utils.data.CollectionUtil;
import com.baseframe.tool.utils.redis.CommonRedisUtil;
import com.baseframe.tool.utils.spring.SpringUtil;
import com.baseframe.user.entity.BaseUser;
import com.baseframe.user.feign.BaseUseFeign;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;

import java.util.List;
import java.util.Map;

import static com.baseframe.auth.constant.BaseAuthConstant.SMS_CAPTCHA_REDIS_KEY;


public class BaseSmsTokenGranter extends AbstractTokenGranter {
    private static final String GRANT_TYPE = "sms";
    protected BaseSmsTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) {
        super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
    }

    @Override
    protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {

        Map<String, String> requestParameters = tokenRequest.getRequestParameters();
        String phone = requestParameters.get("phone");
        String code = requestParameters.get("code");
        //获取redis中的验证码
        String codeKey = SMS_CAPTCHA_REDIS_KEY + phone;
        String redisCode = CommonRedisUtil.getValue(codeKey);
        //删除验证码避免复用
        CommonRedisUtil.delete(codeKey);
        if (code==null||!code.equals(redisCode)){
            throw new UserDeniedAuthorizationException("验证码错误~");
        }
//        //获取手机号码对应的用户信息
//        //微服务应用，这里是获取openFeign
        BaseUseFeign baseUseFeign = SpringUtil.getBean(BaseUseFeign.class);
        R<BaseUser> baseUserR = baseUseFeign.findAllByPhone(phone);
        BaseUser baseUser = baseUserR.getData();
        if (baseUser==null){
            throw new UserDeniedAuthorizationException("该手机未绑定本平台账号，请绑定后重试~");
        }
        //判断用户状态
        if (baseUser.getStatus()==0){
            throw  new InternalAuthenticationServiceException("当前账号已经已被封禁，无法登录");
        }
        //获取权限信息
        BaseSystemFeign baseSystemFeign = SpringUtil.getBean(BaseSystemFeign.class);
        R<List<BasePermission>> permissionListR = baseSystemFeign.findPermissionListByRoleId(baseUser.getRoleId());
        List<BasePermission> permissions = permissionListR.getData();
        if (CollectionUtil.isEmpty(permissions)){
            throw new UserDeniedAuthorizationException("获取用户角色权限信息失败~");
        }

        //类型转换
        BaseUserDetails userDetails = WrapperUtil.buildUserDetails(baseUser,permissions, Kv.create());

        //关闭密码校验
        AbstractAuthenticationToken userAuth = new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities() );
        userAuth.setDetails(requestParameters);
        //组装认证数据
        OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
        //返回 OAuth2Authentication
        return new OAuth2Authentication(storedOAuth2Request, userAuth);
    }
}
